package com.hjm.strategy.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hjm.common.api.ls.leshua.LeShuaUtil;
import com.hjm.common.api.ls.leshua.entity.AccountAmount;
import com.hjm.common.exception.BusinessException;
import com.hjm.common.utils.StringUtils;
import com.hjm.project.area.mapper.AreaMapper;
import com.hjm.project.channel.agent.domain.ChannelAgent;
import com.hjm.project.channel.agent.domain.request.AgentRequest;
import com.hjm.project.channel.agent.domain.request.ChannelBaseInfo;
import com.hjm.project.channel.agent.domain.request.ChannelPicturesInfo;
import com.hjm.project.channel.agent.domain.request.ChannelSettleInfo;
import com.hjm.project.channel.payment.domain.ChannelPayment;
import com.hjm.strategy.AgentStrategy;
import com.hjm.strategy.Channel;
import com.hjm.strategy.kdb.KdbConfig;
import com.hjm.strategy.kdb.KdbRequestHelper;
import com.hjm.strategy.kdb.RandomCodeUtil;
import com.hjm.strategy.kdb.UploadUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Channel("KDB")
@Component
@Slf4j
public class KdbAgentStrategy implements AgentStrategy {

    @Autowired
    private AreaMapper areaMapper;

    @Override
    public void addAgent(ChannelAgent channelAgent, AgentRequest request) {
        try {
            Map<String, Object> root = buildKdbAgentRequest(channelAgent, request);
            String bodyJson = JSON.toJSONString(root);
            String url = KdbConfig.BASE_URL + "/open-api/merchant";
            String response = KdbRequestHelper.send(url, "addAgent", bodyJson);
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.getInteger("code") == 200) {
                JSONObject responseVal = jsonObject.getJSONObject("body");
                channelAgent.setCAgentId(responseVal.getString("agentCode"));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void updateAgent(ChannelAgent channelAgent, AgentRequest request) {
        try {
            Map<String, Object> root = buildKdbAgentRequest(channelAgent, request);
            String bodyJson = JSON.toJSONString(root);
            String url = KdbConfig.BASE_URL + "/open-api/merchant";
            String bizType = "";
            if (StringUtils.isEmpty(channelAgent.getCAgentId())) {
                bizType = "addAgent";
            } else {
                bizType = "modifySettlement";
            }
            String response = KdbRequestHelper.send(url, bizType, bodyJson);
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.getInteger("code") == 200) {
                JSONObject responseVal = jsonObject.getJSONObject("body");
                channelAgent.setCAgentId(responseVal.getString("agentCode"));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String uploadFile(String localPath) {
        try {
            //String fileType = localPath.substring(localPath.lastIndexOf('.') + 1);
            String base64 = UploadUtil.resolveBase64(localPath);
            Map<String, String> fileMap = new HashMap<>();
            fileMap.put("file", base64);
            String bodyJson = JSON.toJSONString(fileMap);
            String url = KdbConfig.BASE_URL + "/open-oss/oss/unify/upload";
            String response = KdbRequestHelper.send(url, "upload", bodyJson);
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.getInteger("code") == 200) {
                JSONObject responseVal = jsonObject.getJSONObject("body");
                return responseVal.getString("ossId");
            }
            throw new RuntimeException("KDB 文件上传失败");
        } catch (Exception e) {
            throw new RuntimeException("KDB 文件上传失败: " + e.getMessage(), e);
        }
    }
    @Override
    public void withdraw(ChannelPayment channelPayment) {
        String walletType = geWalletType(channelPayment);
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("walletType", walletType);
            params.put("channelCode", "LS");
            params.put("otherAgentCode", channelPayment.getApplyAgentId());
            params.put("amount", LeShuaUtil.changeMoneyToFen(channelPayment.getApplyAmount()));
            String url = KdbConfig.BASE_URL + "/open-api/merchant";
            String body = JSON.toJSONString(params);
            String response = KdbRequestHelper.send(url, "withdrawCash", body);
            JSONObject respJson = JSON.parseObject(response);
            if (respJson.getBooleanValue("success") && "200".equals(respJson.getString("code"))) {
                JSONObject bodyJson = respJson.getJSONObject("body");
                channelPayment.setBusinessNo(bodyJson.getString("businessNo"));
                channelPayment.setStatus(3);
            } else {
                channelPayment.setRemark(respJson.getString("msg"));
                channelPayment.setStatus(2);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
    @Override
    public void transfer(ChannelPayment channelPayment) {
        String walletType = geWalletType(channelPayment);
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("walletType", walletType);
            params.put("channelCode", "LS");
            params.put("otherAgentCode", channelPayment.getApplyAgentId());
            params.put("amount", LeShuaUtil.changeMoneyToFen(channelPayment.getApplyAmount()));
            String body = JSON.toJSON(params).toString();
            String url = KdbConfig.BASE_URL + "/open-api/merchant";
            String response = KdbRequestHelper.send(url, "transferAccount", body);
            JSONObject respJson = JSON.parseObject(response);
            if (respJson.getBooleanValue("success") && "200".equals(respJson.getString("code"))) {
                channelPayment.setStatus(1);
            } else {
                channelPayment.setStatus(2);
                channelPayment.setRemark(respJson.getString("msg"));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private String geWalletType(ChannelPayment channelPayment) {
        String walletType;
        if (channelPayment.getAccountType().equals("11")) {
            walletType = "1";
        } else if (channelPayment.getAccountType().equals("12")) {
            walletType = "2";
        } else if (channelPayment.getAccountType().equals("13")) {
            walletType = "3";
        } else if (channelPayment.getAccountType().equals("14")) {
            walletType = "4";
        } else {
            throw new BusinessException(("账户类型错误"));
        }
        return walletType;
    }

    @Override
    public void queryTransfer(ChannelPayment channelPayment) {

    }



    @Override
    public void queryWithdraw(ChannelPayment channelPayment) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("businessNo", channelPayment.getBusinessNo());
            params.put("channelCode", "LS");
            String body = JSON.toJSON(params).toString();
            String url = KdbConfig.BASE_URL + "/open-api/merchant";
            String response = KdbRequestHelper.send(url, "queryWithdrawCash", body);
            JSONObject respJson = JSON.parseObject(response);
            if (respJson.getBooleanValue("success") && "200".equals(respJson.getString("code"))) {
                JSONObject bodyJson = respJson.getJSONObject("body");
                if (bodyJson.getInteger("payStatus") == 0) {
                    channelPayment.setStatus(3);
                } else if (bodyJson.getInteger("payStatus") == 1) {
                    channelPayment.setStatus(1);
                } else if (bodyJson.getInteger("payStatus") == 2) {
                    channelPayment.setStatus(2);
                } else if (bodyJson.getInteger("payStatus") == 3) {
                    channelPayment.setStatus(2);
                } else if (bodyJson.getInteger("payStatus") == 4) {
                    channelPayment.setStatus(2);
                }
                channelPayment.setRemark(bodyJson.getString("payMsg"));
            } else {
                channelPayment.setStatus(2);
                channelPayment.setRemark(respJson.getString("msg"));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public AccountAmount queryBalance(ChannelAgent channelAgent) {
        try {
            AccountAmount amount = new AccountAmount();
            // 循环四种钱包类型
            for (int walletType = 1; walletType <= 4; walletType++) {
                Map<String, Object> params = new HashMap<>();
                params.put("walletType", String.valueOf(walletType));
                params.put("channelCode", "LS");
                params.put("otherAgentCode", channelAgent.getCAgentId());
                String body = JSON.toJSONString(params);
                String url = KdbConfig.BASE_URL + "/open-api/merchant";
                String response = KdbRequestHelper.send(url, "queryBalance", body);
                try {
                    JSONObject respJson = JSON.parseObject(response);
                    if (respJson.getBooleanValue("success") && "200".equals(respJson.getString("code"))) {
                        JSONObject bodyJson = respJson.getJSONObject("body");
                        BigDecimal balance = bodyJson != null ? LeShuaUtil.changeMoneyToYuan(bodyJson.getString("balance")) : BigDecimal.ZERO;
                        switch (walletType) {
                            case 1:
                                amount.setProfit(balance);
                                break;
                            case 2:
                                amount.setFlowCard(balance);
                                break;
                            case 3:
                                amount.setServiceFee(balance);
                                break;
                            case 4:
                                amount.setCashback(balance);
                                break;
                            default:
                                break;
                        }
                    } else {
                        log.warn("查询钱包余额失败：walletType={}, response={}", walletType, response);
                    }
                } catch (Exception e) {
                    log.error("解析钱包余额失败：walletType={}, response={}", walletType, response, e);
                }
            }
            return amount;
        } catch (Exception e) {
            log.error("queryBalance{}", e);
        }
        return null;
    }

    public Map<String, Object> buildKdbAgentRequest(ChannelAgent channelAgent, AgentRequest agentRequest) {

        Map<String, Object> root = new HashMap<>();
        ChannelBaseInfo baseInfo = agentRequest.getBaseInfo();
        ChannelSettleInfo settleInfo = agentRequest.getSettleInfo();
        ChannelPicturesInfo picturesInfo = agentRequest.getPicturesInfo();
        Map<String, String> areaCodes = new HashMap<>();
        if (baseInfo.getAgentProvince() != null && baseInfo.getAgentCity() != null && baseInfo.getProvince() != null) {
            areaCodes = areaMapper.findAreaCodes(baseInfo.getAgentProvince(), baseInfo.getAgentCity(), baseInfo.getProvince());
            if (areaCodes == null || areaCodes.isEmpty()) {
                areaCodes = new HashMap<>();
                areaCodes.put("PROVINCECODE", "110000");
                areaCodes.put("CITYCODE", "110100");
                areaCodes.put("DISTRICTCODE", "110105");
            }
        } else {
            areaCodes = new HashMap<>();
            areaCodes.put("PROVINCECODE", "110000");
            areaCodes.put("CITYCODE", "110100");
            areaCodes.put("DISTRICTCODE", "110105");
        }
        // 1. agentInfo
        Map<String, Object> agentInfo = new HashMap<>();

        agentInfo.put("agentName", (baseInfo.getEnterpriseTitle() == null || baseInfo.getEnterpriseTitle().equals("")) ? baseInfo.getLegalPersonName() : baseInfo.getEnterpriseTitle()); // 代理商名称
        agentInfo.put("agentContactPerson", baseInfo.getLegalPersonName()); // 联系人姓名
        agentInfo.put("contactPersonCardNo", baseInfo.getLegalPersonIdCard()); // 联系人身份证
        agentInfo.put("cardType", "4"); // 固定为身份证
        agentInfo.put("englishName", baseInfo.getLegalPersonName()); // 英文名称
        //(1：个体，2：企业，3：小微)
        if (baseInfo.getAgentProperty().equalsIgnoreCase("0")) {
            //企业
            agentInfo.put("enterpriseNature", "2");
            agentInfo.put("cardNo", baseInfo.getCreditCode()); // 营业执照
            agentInfo.put("businessLicense", picturesInfo.getBusinessLicensePic());//营业执照：当商户性质为个体或者企业时必传

        } else if (baseInfo.getAgentProperty().equalsIgnoreCase("1")) {
            //个人
            agentInfo.put("enterpriseNature", "3");
            agentInfo.put("cardNo", baseInfo.getLegalPersonIdCard()); // 身份证号码
        } else {
            //个体
            agentInfo.put("enterpriseNature", "1");
            agentInfo.put("cardNo", baseInfo.getCreditCode()); // 营业执照
            agentInfo.put("businessLicense", picturesInfo.getBusinessLicensePic());//营业执照：当商户性质为个体或者企业时必传
        }

        agentInfo.put("province", areaCodes.get("PROVINCECODE")); // 省编码
        agentInfo.put("city", areaCodes.get("CITYCODE")); // 市编码
        agentInfo.put("area", areaCodes.get("DISTRICTCODE")); // 区编码
        agentInfo.put("notifyUrl", "http://test.com"); // 回调地址（你可自定义）
        agentInfo.put("address", baseInfo.getAgentAddress()); // 地址
        agentInfo.put("userAccount", agentRequest.getContactInfo().getContactMobile()); // 登录账号
        agentInfo.put("phone", agentRequest.getContactInfo().getContactMobile()); // 联系电话

        // 2. settlementInfo
        Map<String, Object> settlementInfo = new HashMap<>();
        settlementInfo.put("accountType", settleInfo.getBankAccountType().equalsIgnoreCase("2") ? "0" : "1"); // 对公对私，默认 1  0：对公 1：对私
        settlementInfo.put("bankAccountName", settleInfo.getBankCardHolder()); // 开户名
        settlementInfo.put("bankCardAccount", settleInfo.getBankAccountNo()); // 银行卡号
        settlementInfo.put("bankPhone", settleInfo.getBankMobile()); // 银行预留手机号
        settlementInfo.put("bankId", settleInfo.getBankId()); // 银行编号（大行号）
        settlementInfo.put("branchId", settleInfo.getBankUnionpayCode()); // 支行编号
        settlementInfo.put("cardType", "1"); // 身份证
        settlementInfo.put("cardNo", baseInfo.getLegalPersonIdCard()); // 身份证
        settlementInfo.put("cardValidityPeriod", baseInfo.getLegalPersonCertEndDate()); // 有效期
        settlementInfo.put("idCard", baseInfo.getLegalPersonIdCard()); // 冗余

        settlementInfo.put("idCardFront", picturesInfo.getIdCardFrontPic()); // 身份证正面 OSS ID
        settlementInfo.put("idCardBack", picturesInfo.getIdCardBackPic()); // 身份证反面 OSS ID
        settlementInfo.put("bankNo", areaCodes.get("PROVINCECODE")); // 银行所在省
        settlementInfo.put("branchNo", areaCodes.get("CITYCODE")); // 银行所在市

        if (settleInfo.getBankAccountType().equalsIgnoreCase("2")) {
            settlementInfo.put("accountOpeningLicense", picturesInfo.getPublicAccountPic());//开户许可 当账号类型为对公时必传
        } else {
            settlementInfo.put("bankCard", picturesInfo.getSettleBankCardFrontPic()); // 银行卡图片ossid
        }
        if (StringUtils.isNotEmpty(channelAgent.getCAgentId())) {
            root.put("agentInfo", agentInfo);
        }
        // 3. 组装
        root.put("settlementInfo", settlementInfo);

        return root;
    }

}
